10 定时器输入实验
up的视频讲解先用两路相位判断编码器方向,再用捕获值测量两次边沿之间的时间。
up视频里的正交编码实验代码: 👣正交编码实验代码
up视频里的输入捕获实验代码: 👣输入捕获实验代码
1 🔃定时器正交编码实验
1.1 实验连接
编码器 A、B 两路分别连接 PA8、PA9,电源与地按图连接。

1.2 实验原理
编码器内部的两组开关交替动作,形成有相位差的 A、B 信号。两路的变化先后,包含了旋转方向的信息。

按照图中方向,一个周期的状态依次为 11 → 01 → 00 → 10 → 11;反方向则按相反顺序变化。不能只数其中一路的脉冲,还要结合另一路的状态判断方向。

| 编码器模式 | 计数依据 |
|---|---|
| TI12 | 两路边沿参与计数,一个完整信号周期可产生四次计数 |
| TI1 | 一路触发计数,另一路辅助判断方向 |
| TI2 | 与 TI1 对应,交换参与触发的输入通路 |

1.3 CubeMX配置


1.4 实验代码
全局
main()
HAL_TIM_Encoder_Start(&htim1,TIM_CHANNEL_ALL);
uint16_t counter = 0;
while(1)里面
counter =__HAL_TIM_GET_COUNTER(&htim1);
if(counter == 2)
{
//LED1
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,1);//黄灯亮
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,0);//红灯灭
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,1);//蓝灯灭
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,1);//绿灯灭
}
else if(counter ==4)
{
//LED2
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,0);//黄灯灭
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,1);//红灯灭
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,1);//蓝灯灭
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,1);//绿灯灭
}
else if(counter == 6)
{
//LED3
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,0);//黄灯灭
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,0);//红灯灭
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,0);//蓝灯灭
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,1);//绿灯灭
}
else if(counter == 8)
{
//LED4
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,0);//黄灯灭
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,0);//红灯灭
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,1);//蓝灯灭
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,0);//绿灯灭
}
else{
//LED关闭
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,0);//黄灯灭
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_2,0);//红灯灭
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,1);//蓝灯灭
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,1);//绿灯灭
}
2 🔃定时器输入捕获实验
2.1 实验连接
编码器 A 路连接 PA8,串口发送引脚 PA9 连接 CH340 的 RXD,用于观察捕获结果。

2.2 实验原理
把输入配置为下降沿捕获后,每出现一个下降沿,硬件便把当前 CNT 值保存到 CCR。程序在捕获回调中读取并记录它。

先计算一个计数间隔,再乘以经过的计数数量:
计数间隔 = (PSC + 1) ÷ 定时器输入时钟
两次边沿间隔 = 经过的计数数量 × 计数间隔

读程序时,分别找到第一次记录、第二次记录与结果输出的位置。定时器存在计数范围,跨越周期边界时要结合这一点理解捕获结果。
2.3 CubeMX配置



2.4 实验代码
全局
uint8_t flag = 0;
uint32_t cnt1 = 0;
uint32_t cnt2 = 0;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM1)
{
if(flag == 0)
{
//cnt1
cnt1 = HAL_TIM_ReadCapturedValue(&htim1,TIM_CHANNEL_1);
flag++;
}
else if(flag == 1)
{
//cnt2
cnt2 = HAL_TIM_ReadCapturedValue(&htim1,TIM_CHANNEL_1);
flag++;
}
}
}
main()
HAL_TIM_IC_Start_IT(&htim1,TIM_CHANNEL_1);
float time = 0;
while(1)里面
if(flag == 2)
{
//cnt2-cnt1 * T
if(cnt2-cnt1<0)
{
cnt2 += 65536;
}
time = (cnt2-cnt1)*0.0001;
printf("cnt1 = %d cnt2 = %d time = %f \r\n",cnt1,cnt2,time);
flag = 0;
}